import * as THREE from 'three';
import {RigidBody} from '@react-three/rapier';
import {useMemo, useRef, useState} from 'react';
import {useFrame} from '@react-three/fiber';
import {AnimatedWoman} from './AnimatedWoman.jsx';
import {Burger} from './Burger.jsx';
import {BaseBlock} from './block/BaseBlock.jsx';

const geometry = new THREE.BoxGeometry(1, 1, 1);

const floors = [
  new THREE.MeshStandardMaterial({color: 'limegreen'}),
  new THREE.MeshStandardMaterial({color: 'greenyellow'}),
];
const obstacle = new THREE.MeshStandardMaterial({color: 'orangered'});
const wall = new THREE.MeshStandardMaterial({color: 'slategrey'});

const BlockStartOld = ({position = [0, 0, 0]}) => {
  return (
    <group position={position}>
      <BaseBlock geometry={geometry} color={0} />
    </group>
  );
};
const BlockEnd = ({position = [0, 0, 0]}) => {

  console.log('BlockEnd', position);

  return (
    <group position={position}>
      <mesh
        geometry={geometry}
        material={floors[0]}
        position={[0, 0, 0]}
        scale={[4, 0.2, 4]}
        receiveShadow
        castShadow
      />
      <RigidBody type={'fixed'} colliders={null} position={[0, 0.3, 0]} restitution={0} friction={0}>
        <Burger />
      </RigidBody>
    </group>
  );
};

export const BlockSpinner = ({position = [0, 0, 0]}) => {

  const obstacleRef = useRef();

  const [speed] = useState(() => {
    return (Math.random() + 0.2) * Math.random() > 0.5 ? 1 : -1;
  });

  useFrame((state) => {
    const time = state.clock.getElapsedTime();

    const rotation = new THREE.Quaternion();
    rotation.setFromEuler(new THREE.Euler(0, time * speed, 0));
    obstacleRef.current.setNextKinematicRotation(rotation);
  });

  return (
    <group position={position}>
      <mesh
        geometry={geometry}
        material={floors[1]}
        position={[0, -0.1, 0]}
        scale={[4, 0.2, 4]}
        receiveShadow
        castShadow
      />
      <RigidBody ref={obstacleRef} type={'kinematicPosition'} position={[0, 0.3, 0]} restitution={0} friction={0}>
        <mesh
          geometry={geometry}
          material={obstacle}
          position={[0, 0, 0]}
          scale={[3.5, 0.3, 0.3]}
          castShadow
          receiveShadow
        />
      </RigidBody>

    </group>
  );
};

export const BlockLimbo = ({position = [0, 0, 0]}) => {

  const obstacleRef = useRef();

  const [timeOffset] = useState(() => {
    return Math.random() * Math.PI * 2;
  });

  useFrame((state) => {
    const time = state.clock.getElapsedTime();
    const y = Math.sin(time * timeOffset) + 1.15;
    obstacleRef.current.setNextKinematicTranslation({x: position[0], y: position[1] + y, z: position[2]});
  });

  return (
    <group position={position}>
      <mesh
        geometry={geometry}
        material={floors[1]}
        position={[0, -0.1, 0]}
        scale={[4, 0.2, 4]}
        receiveShadow
        castShadow
      />
      <RigidBody ref={obstacleRef} type={'kinematicPosition'} position={[0, 0.3, 0]} restitution={0} friction={0}>
        <mesh
          geometry={geometry}
          material={obstacle}
          scale={[3.5, 0.3, 0.3]}
          receiveShadow
          castShadow
        />
      </RigidBody>

    </group>
  );
};

export const BlockAxe = ({position = [0, 0, 0]}) => {

  const obstacleRef = useRef();

  const [timeOffset] = useState(() => {
    return Math.random() * Math.PI * 2;
  });

  useFrame((state) => {
    const time = state.clock.getElapsedTime();
    const x = Math.sin(time * timeOffset) * 1.25;
    obstacleRef.current.setNextKinematicTranslation({x: position[0] + x, y: position[1] + 0.75, z: position[2]});
  });

  return (
    <group position={position}>
      <mesh
        geometry={geometry}
        material={floors[1]}
        position={[0, -0.1, 0]}
        scale={[4, 0.2, 4]}
        receiveShadow
        castShadow
      />
      <RigidBody ref={obstacleRef} type={'kinematicPosition'} position={[0, 0.3, 0]} restitution={0} friction={0}>
        <mesh
          geometry={geometry}
          material={obstacle}
          scale={[1.5, 1.5, 0.3]}
          receiveShadow
          castShadow
        />
      </RigidBody>

    </group>
  );
};

const Level = ({count = 5, types = [BlockSpinner, BlockLimbo, BlockAxe]}) => {

  // console.log(count, types);

  const blocks = useMemo(() => {
    return Array.from({length: count}, (_, i) => {
      return types[Math.floor(Math.random() * types.length)];
    });
  }, [count, types])

  return (
    <>
      {/* <BlockStart position={[0, 0, 16]}/>
      <BlockSpinner position={[0, 0, 12]}/>
      <BlockLimbo position={[0, 0, 8]}/>
      <BlockAxe position={[0, 0, 4]}/>
      <BlockEnd position={[0, 0, 0]}/> */}

      <BlockStartOld position={[0, 0, 0]}/>
      {blocks.map((Block, i) => {
        return <Block key={i} position={[0, 0, ( i + 1 ) * -4]}/>
      })}

      <BlockEnd position={[0, 0, ( count + 1 ) * -4]}/>
      <AnimatedWoman  position={[0, 0, 0]} />
    </>
  );
};

export default Level;
